﻿// Hongsh.HongshExtends
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Linq;
using System.Xml.Serialization;
using MapleLeaf.Pay;
using Newtonsoft.Json;

public static class HongshExtends {
    public static readonly JsonSerializerSettings MinJsonSerializerSettings;

    public static Dictionary<int, string> GetEnumDictionary<T>() where T : Enum {
        IEnumerator enumerator = typeof(T).GetEnumValues().GetEnumerator();
        Dictionary<int, string> dictionary = new Dictionary<int, string>();
        while (enumerator.MoveNext()) {
            dictionary[(int)enumerator.Current] = typeof(T).GetEnumName(enumerator.Current);
        }
        return dictionary;
    }
    public static T ReadOrDefault<T>(this IDictionary src, object key) {
        return src.Contains(key) ? ((string)src[key]).ConvertTo<T>() : default(T);
    }

    public static T ReadOrDefault<T>(this IDictionary src, object key, T @default) {
        return src.Contains(key) ? ((string)src[key]).ConvertTo<T>() : @default;
    }

    public static TValue ReadOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> src, TKey key) {
        TValue value;
        return src.TryGetValue(key, out value) ? value : default(TValue);
    }

    public static TValue ReadOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> src, TKey key, TValue @default) {
        TValue value;
        return src.TryGetValue(key, out value) ? value : @default;
    }

    public static IDictionary<string, object> ToDictionary<T>(this T src) {
        return src?.GetType().ToDictionary(src);
    }

    public static IDictionary<string, object> ToDictionary(this Type src, object obj) {

        IDictionary<string, object> result;
        if (typeof(IDictionary<string, object>).IsAssignableFrom(src)) {
            result = (IDictionary<string, object>)obj;
        }
        if (src.IsGenericType) {
            Type genericTypeDefinition = src.GetGenericTypeDefinition();
            if (genericTypeDefinition == typeof(IEnumerable<>)) {
                Dictionary<string, object> dictionary = new Dictionary<string, object>();
                Type type = genericTypeDefinition.GetGenericArguments()[0];
                IEnumerator enumerator = ((IEnumerable)obj).GetEnumerator();
                if (type.IsGenericType && type == typeof(KeyValuePair<,>)) {
                    PropertyInfo property = type.GetProperty("Key");
                    PropertyInfo property2 = type.GetProperty("Value");
                    while (enumerator.MoveNext()) {
                        dictionary.Add(property.GetValue(enumerator.Current, null).ToString(), property2.GetValue(enumerator.Current, null));
                    }
                }
                else {
                    int num = 0;
                    while (enumerator.MoveNext()) {
                        dictionary.Add(num.ToString(), enumerator.Current);
                        num++;
                    }
                }
                return dictionary;
            }
        }
        result = src.GetProperties().ToDictionary((PropertyInfo p) => p.Name, (PropertyInfo p) => p.GetValue(obj, null));

        return result;
    }

    public static string GetMessage(this Exception e) {
        List<string> list = new List<string>();
        while (e != null) {
            list.Add(e.Message);
            e = e.InnerException;
        }
        return string.Join(Environment.NewLine, list);
    }

    public static void TryThrow(this Exception src) {
        if (src != null) {
            throw src;
        }
    }

    public static bool IsNullOrEmpty(this string src) {
        return string.IsNullOrEmpty(src);
    }

    public static bool IsNullOrEmpty<T>(this ICollection<T> src) {
        return src == null || src.Count <= 0;
    }

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> src) {
        return src == null || !src.Any();
    }

    public static T ConvertTo<T>(this string src) {
        return (T)src.ConvertTo(typeof(T));
    }

    public static object ConvertTo(this string src, Type type) {
        if (src.GetType() == type) {
            return src;
        }
        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) {
            object result = Activator.CreateInstance(type);
            if (src != null) {
                try {
                    result = src.ConvertTo(Nullable.GetUnderlyingType(type));
                }
                catch {
                }
            }
            return result;
        }
        if (src == null || src is DBNull) {
            return type.IsValueType ? ObjectBuilder.New(type) : null;
        }
        if (typeof(Enum).IsAssignableFrom(type)) {
            return Enum.ToObject(type, src);
        }
        if (type == typeof(DateTime) && src is string && src.Length == 14) {
            return DateTime.ParseExact(src, "yyyyMMddHHmmss", CultureInfo.CurrentCulture);
        }
        return Convert.ChangeType(src, type);
    }

    public static List<T> ToList<T>(this Array src) {
        List<T> list = new List<T>();
        foreach (object item in src) {
            list.Add((T)item);
        }
        return list;
    }

    public static TResult WaitGetResult<TResult>(this Task<TResult> task) {
        task.Wait();
        return task.Result;
    }

    public static byte[] ReadBytes(this Stream s, int len) {
        byte[] array = new byte[len];
        s.Read(array, 0, array.Length);
        return array;
    }

    public static int ReadInt16BigEndian(this Stream s) {
        byte[] array = new byte[2];
        array[1] = (byte)s.ReadByte();
        array[0] = (byte)s.ReadByte();
        return BitConverter.ToInt16(array, 0);
    }

    public static int ReadInt24BigEndian(this Stream s) {
        byte[] array = new byte[4];
        array[2] = (byte)s.ReadByte();
        array[1] = (byte)s.ReadByte();
        array[0] = (byte)s.ReadByte();
        return BitConverter.ToInt16(array, 0);
    }

    public static HttpWebRequest PostJson(this WebRequest r, object data, Encoding e) {
        return r.PostJsonString(data.JsonEncode(), e);
    }

    public static HttpWebRequest PostJsonString(this WebRequest r, string str, Encoding e) {
        r.ContentType = "application/json;charset=" + e.WebName;
        return r.Post(str, e);
    }

    public static HttpWebRequest PostXml(this WebRequest r, XElement data, Encoding e) {
        return PostXml2(r, data.ToXElement("xml"), e);
    }

    public static HttpWebRequest PostXml2(this WebRequest r, XElement data, Encoding e) {
        return r.PostXmlString(data.ToString(SaveOptions.DisableFormatting), e);
    }

    public static HttpWebRequest PostXmlString(this WebRequest r, string str, Encoding e) {
        r.ContentType = "text/xml;charset=" + e.WebName;
        return r.Post(str, e);
    }

    public static HttpWebRequest PostUrlEncoded(this WebRequest r, object data, Encoding e) {
        return r.PostUrlEncoded(data.ToDictionary(), e);
    }

    public static HttpWebRequest PostUrlEncoded(this WebRequest r, IDictionary<string, object> data, Encoding e) {
        return r.PostUrlEncodedString(data.UrlEncode(), e);
    }

    public static HttpWebRequest PostUrlEncodedString(this WebRequest r, string str, Encoding e) {
        r.ContentType = "application/x-www-form-urlencoded;charset=" + e.WebName;
        return r.Post(str, e);
    }

    public static HttpWebRequest Post(this WebRequest r, string str, Encoding e) {
        return r.Post(string.IsNullOrEmpty(str) ? null : e.GetBytes(str));
    }

    public static HttpWebRequest Post(this WebRequest r, byte[] data) {
        if (data != null) {
            if (r.Method != "POST") {
                r.Method = "POST";
            }
            Stream requestStream = r.GetRequestStream();
            requestStream.Write(data, 0, data.Length);
            requestStream.Flush();
        }
        return (HttpWebRequest)r;
    }

    public static HttpWebRequest UseCert(this WebRequest r, X509Certificate cert) {
        if (cert != null) {
            ((HttpWebRequest)r).ClientCertificates.Add(cert);
        }
        return (HttpWebRequest)r;
    }

    public static HttpWebRequest UseTimeOut(this WebRequest r, int time_out) {
        int num3 = (((HttpWebRequest)r).ReadWriteTimeout = (r.Timeout = time_out));
        return (HttpWebRequest)r;
    }

    public static HttpWebRequest UseProxy(this WebRequest r, IWebProxy proxy) {
        r.Proxy = proxy;
        return (HttpWebRequest)r;
    }

    public static string ReadString(this WebRequest r, Encoding e) {
        return r.GetResponse().ReadString(e);
    }

    public static string ReadString(this WebResponse r, Encoding e) {
        return new StreamReader(r.GetResponseStream(), e).ReadToEnd();
    }

    public static bool IsRecvingException(this WebException e) {
        return e.Status == WebExceptionStatus.ReceiveFailure || e.Status == WebExceptionStatus.ConnectionClosed || e.Status == WebExceptionStatus.ServerProtocolViolation || e.Status == WebExceptionStatus.KeepAliveFailure || e.Status == WebExceptionStatus.Timeout || e.Status == WebExceptionStatus.UnknownError;
    }

    public static string HexEncode(this byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        foreach (byte b in src) {
            stringBuilder.AppendFormat("{0:x2}", b);
        }
        return stringBuilder.ToString();
    }

    public static byte[] HexDecode(this string src) {
        byte[] array = new byte[src.Length / 2];
        for (int i = 0; i < array.Length; i++) {
            array[i] = Convert.ToByte(src.Substring(i * 2, 2), 16);
        }
        return array;
    }

    public static string UrlEncode<T>(this IEnumerable<KeyValuePair<string, T>> src, Encoding e = null) {
        return src.Select(delegate (KeyValuePair<string, T> kv) {
            string key = kv.Key;
            T value = kv.Value;
            return new KeyValuePair<string, string>(key, (value != null) ? value.ToString() : null);
        }).UrlEncode(e);
    }

    public static string UrlEncode(this IEnumerable<KeyValuePair<string, string>> src, Encoding e = null) {
        StringBuilder stringBuilder = new StringBuilder();
        foreach (KeyValuePair<string, string> item in src) {
            if (!string.IsNullOrEmpty(item.Value)) {
                if (stringBuilder.Length > 0) {
                    stringBuilder.Append("&");
                }
                stringBuilder.Append(item.Key);
                stringBuilder.Append("=");
                stringBuilder.Append((e == null) ? item.Value : HttpUtility.UrlEncode(item.Value, e));
            }
        }
        return stringBuilder.ToString();
    }

    public static string Base64Encode(this byte[] src) {
        return (src == null) ? null : Convert.ToBase64String(src);
    }

    public static byte[] Base64Decode(this string src) {
        return (src == null) ? null : Convert.FromBase64String(src);
    }

    public static string UrlBase64Encode(this byte[] src) {
        char[] array = src.Base64Encode().ToCharArray();
        for (int i = 0; i < array.Length; i++) {
            switch (array[i]) {
                case '=':
                    array[i] = '!';
                    break;
                case '/':
                    array[i] = '_';
                    break;
                case '+':
                    array[i] = '-';
                    break;
            }
        }
        return new string(array);
    }

    public static byte[] UrlBase64Decode(this string src) {
        char[] array = src.ToCharArray();
        for (int i = 0; i < array.Length; i++) {
            switch (array[i]) {
                case '_':
                    array[i] = '/';
                    break;
                case '-':
                    array[i] = '+';
                    break;
                case '!':
                    array[i] = '=';
                    break;
            }
        }
        return Convert.FromBase64CharArray(array, 0, array.Length);
    }

    public static T ToObject<T>(this XElement src) {
        return (T)src.ToObject(typeof(T));
    }

    public static object ToObject(this XElement src, Type type) {
        return new XmlSerializer(type, new XmlRootAttribute(src.Name.LocalName)).Deserialize(src.CreateReader());
    }

    public static XElement ToXElement(this object src, string root) {
        if (src is XElement) {
            return (XElement)src;
        }
        return src.ToDictionary().smethod_1(root);
    }

    public static XElement smethod_1<T>(this IEnumerable<KeyValuePair<string, T>> src, string root) {
        List<XElement> list = new List<XElement>();
        foreach (KeyValuePair<string, T> item in src) {
            if (item.Value == null || item.Value is string || item.Value is ValueType) {
                list.Add(new XElement(item.Key, item.Value));
            }
            else {
                list.Add(((XElement)(object)item.Value).ToXElement(item.Key));
            }
        }
        return new XElement(root, list);
    }

    public static Dictionary<string, object> ToDictionary(this XElement src) {
        return src.ToDictionary<Dictionary<string, object>>();
    }

    public static T ToDictionary<T>(this XElement src) where T : IDictionary<string, object> {
        T result = ObjectBuilder<T>.New();
        foreach (XElement item in src.Elements()) {
            result[item.Name.ToString()] = (item.HasElements ? ((IEnumerable)item.ToDictionary<Dictionary<string, object>>()) : ((IEnumerable)item.Value));
        }
        return result;
    }

    public static XElement smethod_2(this string src) {
        return XElement.Parse(src);
    }

    public static string JsonEncode(this object obj, Formatting fmt = Formatting.None) {
        return JsonConvert.SerializeObject(obj, fmt);
    }

    public static string JsonEncode(this object obj, Type type, Formatting fmt = Formatting.None) {
        return JsonConvert.SerializeObject(obj, type, fmt, null);
    }

    public static T JsonDecode<T>(this string json) {
        return JsonConvert.DeserializeObject<T>(json);
    }

    public static object JsonDecode(this string json, Type type) {
        return JsonConvert.DeserializeObject(json, type);
    }

    public static object[] ReadToArray(this IDataReader r) {
        object[] array = new object[r.FieldCount];
        for (int i = 0; i < r.FieldCount; i++) {
            object value = r.GetValue(i);
            array[i] = ((value == DBNull.Value) ? null : value);
        }
        return array;
    }

    public static T ReadToDictionary<T>(this IDataReader r) {
        IDictionary dictionary;
        if (typeof(T) == typeof(object) || typeof(IDictionary<string, object>).IsAssignableFrom(typeof(T))) {
            dictionary = new Dictionary<string, object>();
            for (int i = 0; i < r.FieldCount; i++) {
                object value = r.GetValue(i);
                dictionary[r.GetName(i)] = ((value == DBNull.Value) ? null : value);
            }
        }
        else {
            dictionary = (IDictionary)(object)ObjectBuilder<T>.New();
            Type[] genericArguments = typeof(T).GetGenericArguments();
            for (int j = 0; j < r.FieldCount; j++) {
                string name = r.GetName(j);
                object value2 = r.GetValue(j);
                if (genericArguments.Length < 2) {
                    dictionary.Add(name, value2);
                }
                else {
                    dictionary.Add(name.ConvertTo(genericArguments[0]), ((string)value2).ConvertTo(genericArguments[1]));
                }
            }
        }
        return (T)dictionary;
    }

    public static T ReadToObject<T>(this IDataReader r) {
        T val = ObjectBuilder<T>.New();
        for (int i = 0; i < r.FieldCount; i++) {
            if (ObjectBuilder<T>.Propertys.TryGetValue(r.GetName(i), out var value)) {
                value.SetValue(val, ((string)r.GetValue(i)).ConvertTo(value.PropertyType), null);
            }
        }
        return val;
    }

    public static T Get<T>(this IDataReader r) {
        if (typeof(IConvertible).IsAssignableFrom(typeof(T))) {
            return ((string)r.GetValue(0)).ConvertTo<T>();
        }
        if (typeof(T) == typeof(object) || typeof(IDictionary).IsAssignableFrom(typeof(T))) {
            return r.ReadToDictionary<T>();
        }
        if (typeof(T) == typeof(object[])) {
            return (T)(object)r.ReadToArray();
        }
        return r.ReadToObject<T>();
    }

    static HongshExtends() {
        MinJsonSerializerSettings = new JsonSerializerSettings {
            NullValueHandling = NullValueHandling.Ignore,
            DefaultValueHandling = DefaultValueHandling.Ignore
        };
    }
}
